#coding:utf-8

import detector
import cv2
import os
import matplotlib.pyplot as plt
import numpy as np
import copy
from skimage.feature import graycomatrix, graycoprops

import examples


################################################################################
'''
此代码实现对单张图片：
1. 应用自适应直方图均衡化
2. 取左上角和右上角ROI
3. 应用单个Gabor卷积核，呈现卷积结果
4. 对卷积结果做线条检测，取平均斜率
5. 根据左右上角纹理的平均斜率取原本方形块的4个点
6. 对取到点的连线所包围的区域做透视变换，使纹理横平竖直
7. 提高图像对比度
8. 对标准化后的图片做gabor滤波
9. 对图片的所有区域做网格化切块，切块大小[140,420]
10. 对所有切块分别计算几个特定的灰度共生矩阵统计量,并展示出来
11. 按行和列挑选离群块，并在图上画出来
'''
def example_10():
    single_img_path = "../fabric-defect/麻皮/T03831_00.bmp"
    img = detector.cv_read(single_img_path)
    img_EquHisto = detector.AdaptiveEquHisto(img)

    # 取左上角的ROI
    top_left = [0,0]
    buttom_right = [120,200]
    roi_top_left = detector.get_roi(img_EquHisto,top_left, buttom_right)

    # 取右上角的ROI
    [height, width] = img_EquHisto.shape

    top_left = [width-121, 0]
    buttom_right = [width-1,200]
    roi_top_right = detector.get_roi(img_EquHisto,top_left, buttom_right)

    ksize = 100 
    params = {'ksize':(ksize, ksize), 
            'sigma':5, 
            'theta':0,                                # theta代表条纹旋转角度
            'lambd':8,                                   # lambd为波长 波长越大 条纹越大
            'gamma':1,                                  # gamma越大核函数图像越小，条纹数不变，sigma越大 条纹和图像都越大
            'psi':0,                                   # psi 是相位偏移 psi这里接近0度以白条纹为中心，180度时以黑条纹为中心
            'ktype':cv2.CV_32F}

    kern = cv2.getGaborKernel(**params)
    roi_top_left_gabor = cv2.filter2D(roi_top_left, -1, kern)
    roi_top_right_gabor = cv2.filter2D(roi_top_right, -1, kern)

    slope_top_left = detector.calc_mean_slope(roi_top_left_gabor)
    slope_top_right = detector.calc_mean_slope(roi_top_right_gabor)

    '''
    已知斜率k与一点(x0, y0)，又知另一点的一个坐标y, 求直线方程上另一点的x。

    (y - y0) = k*(x - x0)
    y - y0 = k*(x - x0)
    (y - y0)/k = x - x0
    x = (y - y0)/k + x0
    '''
    # 透视变换，需要取原图的4个顶点，变换到新的4个位置上
    point_top_left = [0,0]
    point_top_right = [width-1, 0]
    point_buttom_left = [0, height]
    point_buttom_right = [0, height]

    point_buttom_left[0] = (point_buttom_left[1] - point_top_left[1]) / slope_top_left + point_top_left[0]
    point_buttom_right[0] = (point_buttom_right[1] - point_top_right[1]) / slope_top_right + point_top_right[0]

    points = [point_top_left, point_top_right, point_buttom_left, point_buttom_right]

    dst_width = point_buttom_right[0]-point_buttom_left[0]
    dst_width = np.round(dst_width).astype(int)
    dst = [[0,0],[dst_width,0],[0,height],[dst_width,height]]
    img_Standardize = detector.PerspectiveTransform(img_EquHisto,points,dst,(dst_width,height))
    img_contrast = cv2.convertScaleAbs(img_Standardize, alpha=2.5, beta=-100)
    detector.cv_show("img_Standardize",img_Standardize)
    detector.cv_show("img_contrast",img_contrast)


    # 构建Gabor滤波器
    params_set = []
    params_set.append(
        {'ksize':(140, 140), 
        'sigma':35, 
        'theta':0,                                # theta代表条纹旋转角度
        'lambd':7,                                   # lambd为波长 波长越大 条纹越大
        'gamma':0.07,                                  # gamma越大核函数图像越小，条纹数不变，sigma越大 条纹和图像都越大
        'psi':0,                                   # psi 是相位偏移 psi这里接近0度以白条纹为中心，180度时以黑条纹为中心
        'ktype':cv2.CV_32F}
    )

    filters = detector.build_filters(params_set)

    for kern,params in filters:
        img_filted = cv2.filter2D(img_contrast, -1, kern)
    detector.cv_show("img_filted",img_filted,block=True)

    slice_width = 140
    slice_height = 210
    slices, (slice_row, slice_col) = detector.grid_slice_width_height_grid(img_filted,slice_width,slice_height)
    # print(slice_row,slice_col)
    
    dist = 0
    degree = 0
    coprops = {'contrast':0,
            'dissimilarity':0,
            'homogeneity':0,
            'energy':0,
            'correlation':0,
            'ASM':0
    }
    prop = ''
    parameters_tuple = (dist, degree, prop)

    '''
    目标数据:all_slices_dicts, 保存了 所有slice 对于 特定glcm参数组 的 glcm统计量
    格式：长度为len(slices)的一维数组
        元素：字典
                key: 由参数组组成的字符串
                value： 由参数组计算的 glcm统计量
    '''
    parameters_tuple_list = []
    parameters_tuple_list.append((1, 0, 'dissimilarity')) 
    # parameters_tuple_list.append((7, np.pi/2, 'homogeneity'))
    # parameters_tuple_list.append((70, 0, 'homogeneity'))
    parameters_tuple_list.append((70, np.pi/2, 'dissimilarity'))

    def get_parameters_tuple_fstring(parameters_tuple):
        (dist, degree, prop) = parameters_tuple
        return f"dist:{dist:2d}, degree:{degree:1.2f}, prop:{prop}"

    single_slice_dict = {}
    for i in range(len(parameters_tuple_list)):
        single_slice_dict[get_parameters_tuple_fstring(parameters_tuple_list[i])] = 0

    all_slices_dicts = []
    for i in range(len(slices)):
        all_slices_dicts.append(copy.deepcopy(single_slice_dict))
        # 开始计算glcm
        for j in range(len(parameters_tuple_list)):
            (dist, degree, prop) = parameters_tuple_list[j]
            # 压缩图片灰度级
            table16 = np.array([(i//16) for i in range(256)]).astype("uint8")  # 16 levels
            gray16 = cv2.LUT(slices[i], table16)  # 灰度级压缩为 [0,15]
            glcm = graycomatrix(gray16, [dist], [degree], levels=16)
            feature = graycoprops(glcm, prop).round(8)
            all_slices_dicts[i][get_parameters_tuple_fstring((dist, degree, prop))] = feature

    # print(feature.shape)  #(1,1)

    
    for parameters_tuple in parameters_tuple_list:
        glcm_data_matrix = []
        plt.figure(figsize=(slice_row*3, slice_col*3))
        plt.suptitle(single_img_path + ' glcm ' + get_parameters_tuple_fstring(parameters_tuple) 
                     + '\n'+ detector.gen_params_string(params_set[0]),
                     fontproperties = detector.get_font_yahei(13))
        for i in range(slice_row):
            glcm_data_matrix_row = []
            for j in range(slice_col):
                plt.subplot(slice_row,slice_col,i*slice_col+j+1)
                # plt.title(f"{i},{j}")
                plt.title(f"{all_slices_dicts[i*slice_col+j][get_parameters_tuple_fstring(parameters_tuple)][0][0]:.4f}")
                # plt.text(1,50,f"{all_slices_dicts[i*slice_col+j][get_parameters_tuple_fstring(parameters_tuple)][0][0]:.4f}",
                #          color='red',size=14)
                plt.imshow(slices[i*slice_col+j], 'gray')
                glcm_data_matrix_row.append(all_slices_dicts[i*slice_col+j][get_parameters_tuple_fstring(parameters_tuple)][0][0].round(4))

            glcm_data_matrix.append(glcm_data_matrix_row)
        
        # 按行寻找离群值
        # 将离群块绘制在图片上，并展示
        img_result_row = copy.deepcopy(img_Standardize)
        img_result_row = cv2.cvtColor(img_result_row, cv2.COLOR_GRAY2RGB)
        for i in range(slice_row):
            indices = detector.outliers_sigma_indices(np.array(glcm_data_matrix[i]),3)
            for j in range(len(indices)):
                ptLeftTop = (indices[j]*slice_width, i*slice_height)
                ptRightBottom = (indices[j]*slice_width + slice_width, i*slice_height + slice_height)
                point_color = (255, 0, 0)
                thickness = 3 
                lineType = 4
                cv2.rectangle(img_result_row, ptLeftTop, ptRightBottom, point_color, thickness, lineType)
        detector.display_imgs([img_result_row],[""],num_cols=1,
                              main_title=("result_by_row:"+ single_img_path + " " + get_parameters_tuple_fstring(parameters_tuple)
                                          + '\n'+ detector.gen_params_string(params_set[0])))

        # 按列寻找离群值
        # 将离群块绘制在图片上，并展示
        img_result_col = copy.deepcopy(img_Standardize)
        img_result_col = cv2.cvtColor(img_result_col, cv2.COLOR_GRAY2RGB)
        for j in range(slice_col):
            glcm_data_matrix_col = []
            for i in range(slice_row): 
                glcm_data_matrix_col.append(all_slices_dicts[i*slice_col+j][get_parameters_tuple_fstring(parameters_tuple)][0][0].round(4))
            indices = detector.outliers_sigma_indices(np.array(glcm_data_matrix_col),1)
            for i in range(len(indices)):
                ptLeftTop = (j*slice_width, indices[i]*slice_height)
                ptRightBottom = (j*slice_width + slice_width, indices[i] *slice_height + slice_height)
                point_color = (255, 0, 0)
                thickness = 3 
                lineType = 4
                cv2.rectangle(img_result_col, ptLeftTop, ptRightBottom, point_color, thickness, lineType)
        detector.display_imgs([img_result_col],[""],num_cols=1,
                              main_title=("result_by_col:"+ single_img_path + " " + get_parameters_tuple_fstring(parameters_tuple)
                                          + '\n'+ detector.gen_params_string(params_set[0])))
        



    plt.show()




    

    





example_10()

# examples.example_1()





















